unit Keyboard;

{all code by Steven H. Don, i only made it
 into a unit and added the spacebar.. BdR}

{****************************************************************************
** Demonstration of using a custom keyboard handler to detect multiple     **
** cursor keys being held down simultaneously                              **
**  by Steven H Don                                                        **
**                                                                         **
** For questions, feel free to e-mail me.                                  **
**                                                                         **
**    shd@earthling.net                                                    **
**    http://shd.cjb.net                                                   **
**                                                                         **
****************************************************************************}

Interface

Uses Dos;

Var
  {Key status indicators}
  SpaceBarPressed : Boolean;

{Pointer to original keyboard handler}
BIOSHandler : Procedure;

Procedure KeyCheck; interrupt;
Procedure XKey;
Procedure NKey;


{****************************************************************************
** This is the custom keyboard handler. It checks to see if a cursor key   **
** is pressed or release and sets variables accordingly.                   **
****************************************************************************}

{$F+}

implementation

const
  KeycodeSpaceUp   = 128+57;
  KeycodeSpaceDown = 57;

Procedure KeyCheck; {interrupt;}
Var
  CallBIOSHandler : Boolean;
  i : Byte;
Begin
  {Assume BIOS has to be called}
  CallBIOSHandler := true;

  i := port [$60];

  If (i = KeycodeSpaceDown) Then Begin
    SpacebarPressed := true;
    {No need to call BIOS}
    CallBIOSHandler := false;
  end
  Else If (i = KeycodeSpaceUp) Then Begin
    SpacebarPressed := false;
    {No need to call BIOS}
    CallBIOSHandler := false;
  End;

  {If we haven't handled the keypress ourselves...}
  if CallBIOSHandler then begin
    {...let the BIOS take care of it...}
    asm pushf end;
    BIOSHandler;
  end else begin
    {...otherwise, acknowledge the hardware interrupt}
    port [$20] := $20;
  end;
end;
{$F-}

{****************************************************************************
** This procedures installs the custom keyboard handler and saves a        **
** pointer to the original                                                 **
****************************************************************************}
Procedure XKey;
Begin
  {Save BIOS keyboard handler}
  GetIntVec (9, @BIOSHandler);
  {Set interrupt vector to our own routine}
  SetIntVec (9, Addr(KeyCheck));
End;

{****************************************************************************
** This procedures restores the original keyboard handler                  **
*****************************************************************************
** Make sure you call this before exiting your program! Otherwise, the     **
** system will crash                                                       **
****************************************************************************}
Procedure NKey;
Begin
  {Set interrupt vector to the BIOS keyboard handler}
  SetIntVec (9, @BIOSHandler);
End;

{ get keycode }
Function GetKeyDown : Byte;
Var
  CurrKey, PrevKey, FoundKey : Byte;
Begin
  FoundKey := 0;
  PrevKey := Port[$60];
  Repeat
    { get current keycode }
    CurrKey := Port[$60];
    If ((PrevKey+128) = CurrKey) { Caps/Num/Scroll Lock all have keycode down=250 }
    And (PrevKey <> 27) Then     { 'Esc' is not accepted }
      FoundKey := PrevKey;
    { save current keycode }
    PrevKey := CurrKey;
  Until FoundKey <> 0;
  { function result }
  GetKeyDown := FoundKey;
End;

end.